package com.gitee.xqxyxchy.crypto.impl;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.util.encoders.Hex;

import com.gitee.xqxyxchy.crypto.CryptoParam;
import com.gitee.xqxyxchy.crypto.ICryptoService;
import com.gitee.xqxyxchy.crypto.ParamKey;

public class Sm4Crypto implements ICryptoService {

	private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
	private static final String KEY_ALGORITHM = "SM4";
	private static final String DEFAULT_ALGORITHMS = "SM4/CBC/PKCS7Padding";

	@Override
	public String encrypt(String originData, CryptoParam... params) {
		try {
			String privateKey = CryptoParam.Builder.create().get(ParamKey.PRIVATE_KEY.getKey(), params);
			String iv = CryptoParam.Builder.create().get(ParamKey.IV_KEY.getKey(), params);
			Cipher cipher = Cipher.getInstance(DEFAULT_ALGORITHMS, new org.bouncycastle.jce.provider.BouncyCastleProvider());
			SecretKeySpec secretKeySpec = new SecretKeySpec(privateKey.getBytes(DEFAULT_CHARSET), KEY_ALGORITHM);
			// 创建 IvParameterSpec 对象，使用默认向量和字符集
			IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(DEFAULT_CHARSET));
			// 初始化加密实例
			cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
			// 返回加密后的字节数组
			return Hex.toHexString(cipher.doFinal(originData.getBytes(DEFAULT_CHARSET)));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public String decrypt(String encryptedData, CryptoParam... params) {
		try {
			String privateKey = CryptoParam.Builder.create().get(ParamKey.PRIVATE_KEY.getKey(), params);
			String iv = CryptoParam.Builder.create().get(ParamKey.IV_KEY.getKey(), params);
			byte[] decode = Hex.decode(encryptedData);
			Cipher cipher = Cipher.getInstance(DEFAULT_ALGORITHMS, new org.bouncycastle.jce.provider.BouncyCastleProvider());
			SecretKeySpec secretKeySpec = new SecretKeySpec(privateKey.getBytes(DEFAULT_CHARSET), KEY_ALGORITHM);
			IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(DEFAULT_CHARSET));
			cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
			return new String(cipher.doFinal(decode), DEFAULT_CHARSET);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}
